package org.michaelrenaud.pathfinder.client.core.app.character;

import org.michaelrenaud.pathfinder.client.core.app.character.widget.SkillRow;
import org.michaelrenaud.pathfinder.shared.model.Character;
import org.michaelrenaud.pathfinder.shared.model.Class;
import org.michaelrenaud.pathfinder.shared.model.StatBlock;
import org.michaelrenaud.pathfinder.shared.model.StatBlockSkill;
import org.michaelrenaud.pathfinder.shared.model.Trait;
import org.michaelrenaud.pathfinder.shared.model.enumeration.Alignment;
import org.michaelrenaud.pathfinder.shared.model.enumeration.Sex;

import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.gwtplatform.mvp.client.ViewImpl;

public class CharacterView extends ViewImpl implements CharacterPresenter.MyView {
	
	public interface CharacterStyle extends CssResource {
		String checked();
		String classSkill();
	}

	@UiField CharacterStyle style;
	@UiField Label txtPlayer;
	@UiField Label txtCampaign;
	@UiField Label txtXP;
	@UiField Label txtHeroPoints;
	@UiField Label txtStrength;
	@UiField Label txtDexterity;
	@UiField Label txtConstitution;
	@UiField Label txtIntelligence;
	@UiField Label txtWisdom;
	@UiField Label txtCharisma;
	@UiField Label txtSTR;
	@UiField Label txtDEX;
	@UiField Label txtCON;
	@UiField Label txtINT;
	@UiField Label txtWIS;
	@UiField Label txtCHA;
	@UiField Label txtStrengthItemBonus;
	@UiField Label txtDexterityItemBonus;
	@UiField Label txtConstitutionItemBonus;
	@UiField Label txtIntelligenceItemBonus;
	@UiField Label txtWisdomItemBonus;
	@UiField Label txtCharismaItemBonus;
	@UiField Label txtFeat0;
	@UiField Label txtFeat1;
	@UiField Label txtFeat2;
	@UiField Label txtFeat3;
	@UiField Label txtFeat4;
	@UiField Label txtFeat5;
	@UiField Label txtFeat6;
	@UiField Label txtFeat7;
	@UiField Label txtFeat8;
	@UiField Label txtFeat9;
	@UiField Label txtFeat10;
	@UiField Label txtFeat11;
	@UiField Label txtFeat12;
	@UiField Label txtFeat13;
	@UiField Label txtFeat14;
	@UiField Label txtFeat15;
	@UiField Label txtFeat16;
	@UiField Label txtFeat17;
	@UiField Label txtFeat18;
	@UiField Label txtFeat19;
	@UiField Label txtFeat20;
	@UiField Label txtFeat21;
	@UiField Label txtFeat22;
	@UiField Label txtFeat23;
	@UiField Label txtFeat24;
	@UiField Label txtFeat25;
	@UiField Label txtFeat26;
	@UiField Label txtFeat27;
	@UiField Label txtFeat28;
	@UiField Label txtFeat29;
	@UiField Label txtFeat30;
	@UiField Label txtFeat31;
	@UiField Label txtLanguage0;
	@UiField Label txtLanguage1;
	@UiField Label txtLanguage2;
	@UiField Label txtLanguage3;
	@UiField Label txtLanguage4;
	@UiField Label txtLanguage5;
	@UiField HTMLPanel chkLawfulGood;
	@UiField HTMLPanel chkLawfulNeutral;
	@UiField HTMLPanel chkLawfulEvil;
	@UiField HTMLPanel chkNeutralGood;
	@UiField HTMLPanel chkNeutral;
	@UiField HTMLPanel chkNeutralEvil;
	@UiField HTMLPanel chkChaoticGood;
	@UiField HTMLPanel chkChaoticNeutral;
	@UiField HTMLPanel chkChaoticEvil;
	@UiField HTMLPanel chkFavoredClass0;
	@UiField HTMLPanel chkFavoredClass1;
	@UiField HTMLPanel chkFavoredClass2;
	@UiField HTMLPanel chkFavoredClass3;
	@UiField HTMLPanel chkFavoredClass4;
	@UiField Label txtClassName0;
	@UiField Label txtClassName1;
	@UiField Label txtClassName2;
	@UiField Label txtClassName3;
	@UiField Label txtClassName4;
	@UiField Label txtClassSkillRanks0;
	@UiField Label txtClassSkillRanks1;
	@UiField Label txtClassSkillRanks2;
	@UiField Label txtClassSkillRanks3;
	@UiField Label txtClassSkillRanks4;
	@UiField Label txtClassHitDie0;
	@UiField Label txtClassHitDie1;
	@UiField Label txtClassHitDie2;
	@UiField Label txtClassHitDie3;
	@UiField Label txtClassHitDie4;
	@UiField Label txtClassLevel0;
	@UiField Label txtClassLevel1;
	@UiField Label txtClassLevel2;
	@UiField Label txtClassLevel3;
	@UiField Label txtClassLevel4;
	@UiField Label txtName;
	@UiField Label txtRace;
	@UiField Label txtSize;
	@UiField Label txtSizeModifier;
	@UiField HTMLPanel chkMale;
	@UiField HTMLPanel chkFemale;
	@UiField SkillRow skillRow0;
	@UiField SkillRow skillRow1;
	@UiField SkillRow skillRow2;
	@UiField SkillRow skillRow3;
	@UiField SkillRow skillRow4;
	@UiField SkillRow skillRow5;
	@UiField SkillRow skillRow6;
	@UiField SkillRow skillRow7;
	@UiField SkillRow skillRow8;
	@UiField SkillRow skillRow9;
	@UiField SkillRow skillRow10;
	@UiField SkillRow skillRow11;
	@UiField SkillRow skillRow12;
	@UiField SkillRow skillRow13;
	@UiField SkillRow skillRow14;
	@UiField SkillRow skillRow15;
	@UiField SkillRow skillRow16;
	@UiField SkillRow skillRow17;
	@UiField SkillRow skillRow18;
	@UiField SkillRow skillRow19;
	@UiField SkillRow skillRow20;
	@UiField SkillRow skillRow21;
	@UiField SkillRow skillRow22;
	@UiField SkillRow skillRow23;
	@UiField SkillRow skillRow24;
	@UiField SkillRow skillRow25;
	@UiField SkillRow skillRow26;
	@UiField SkillRow skillRow27;
	@UiField SkillRow skillRow28;
	@UiField SkillRow skillRow29;
	@UiField SkillRow skillRow30;
	@UiField SkillRow skillRow31;
	@UiField SkillRow skillRow32;
	@UiField SkillRow skillRow33;
	@UiField SkillRow skillRow34;
	@UiField SkillRow skillRow35;
	
	private final Widget widget;
	
	private Character character;
	private StatBlock statBlock;
	private Label[] lblFeats;
	private Label[] lblLanguages;
	private HTMLPanel[] chkFavoredClasses;
	private Label[] lblClassNames;
	private Label[] lblClassSkillRanks;
	private Label[] lblClassHitDie;
	private Label[] lblClassLevels;
	private SkillRow[] skillRows;
	

	public interface Binder extends UiBinder<Widget, CharacterView> {}

	@Inject
	public CharacterView(final Binder binder) {
		widget = binder.createAndBindUi(this);
		
		lblFeats = new Label[] {txtFeat0, txtFeat1, txtFeat2, txtFeat3, txtFeat4, txtFeat5, txtFeat6, txtFeat7, txtFeat8, txtFeat9,
				 txtFeat10,  txtFeat11,  txtFeat12,  txtFeat13,  txtFeat14,  txtFeat15,  txtFeat16,  txtFeat17,  txtFeat18,  txtFeat19,
				 txtFeat20,  txtFeat21,  txtFeat22,  txtFeat23,  txtFeat24,  txtFeat25,  txtFeat26,  txtFeat27,  txtFeat28, txtFeat29,
				 txtFeat30, txtFeat31};
		
		lblLanguages = new Label[] {txtLanguage0, txtLanguage1, txtLanguage2, txtLanguage3, txtLanguage4, txtLanguage5};
		
		chkFavoredClasses = new HTMLPanel[] {chkFavoredClass0, chkFavoredClass1, chkFavoredClass2, chkFavoredClass3, chkFavoredClass4};
		lblClassNames = new Label[] {txtClassName0, txtClassName1, txtClassName2, txtClassName3, txtClassName4};
		lblClassSkillRanks = new Label[] {txtClassSkillRanks0, txtClassSkillRanks1, txtClassSkillRanks2, txtClassSkillRanks3, txtClassSkillRanks4};
		lblClassHitDie = new Label[] {txtClassHitDie0, txtClassHitDie1, txtClassHitDie2, txtClassHitDie3, txtClassHitDie4};
		lblClassLevels = new Label[] {txtClassLevel0, txtClassLevel1, txtClassLevel2, txtClassLevel3, txtClassLevel4};
		
		skillRows = new SkillRow[] {skillRow0, skillRow1, skillRow2, skillRow3, skillRow4, skillRow5, skillRow6, skillRow7, skillRow8, skillRow9, 
				skillRow10, skillRow11, skillRow12, skillRow13, skillRow14, skillRow15, skillRow16, skillRow17, skillRow18, skillRow19, 
				skillRow20, skillRow21, skillRow22, skillRow23, skillRow24, skillRow25, skillRow26, skillRow27, skillRow28, skillRow29, 
				skillRow30, skillRow31, skillRow32, skillRow33, skillRow34, skillRow35};
	}

	@Override
	public Widget asWidget() {
		return widget;
	}

	@Override
	public void setCharacter(Character character, StatBlock statBlock) {
		this.character = character;
		this.statBlock = statBlock;
		displayCharacter();
	}

	private void displayCharacter() {
		txtPlayer.setText(character.getPlayer());
		txtCampaign.setText(character.getCampaign());
		txtXP.setText(character.getXP() + " points");
		txtHeroPoints.setText(character.getHeroPoints() + "/3"); // TODO Feat
		setSex(character.getSex());
		setAlignment(character.getAlignment());
		txtName.setText(character.getName());
		txtRace.setText(character.getRace().getName());
		txtRace.setTitle(character.getRace().getDescription());
		txtSize.setText(statBlock.getSizeText());
		txtSizeModifier.setText(statBlock.getSizeModifier().getTotal() + "");
		txtSizeModifier.setTitle(statBlock.getSizeModifier().getTooltip());
		
		// Ability Score
		txtStrength.setText(statBlock.getStrength().getTotal() + "");
		txtStrength.setTitle(statBlock.getStrength().getTooltip());
		txtDexterity.setText(statBlock.getDexterity().getTotal() + "");
		txtDexterity.setTitle(statBlock.getDexterity().getTooltip());
		txtConstitution.setText(statBlock.getConstitution().getTotal() + "");
		txtConstitution.setTitle(statBlock.getConstitution().getTooltip());
		txtIntelligence.setText(statBlock.getIntelligence().getTotal() + "");
		txtIntelligence.setTitle(statBlock.getIntelligence().getTooltip());
		txtWisdom.setText(statBlock.getWisdom().getTotal() + "");
		txtWisdom.setTitle(statBlock.getWisdom().getTooltip());
		txtCharisma.setText(statBlock.getCharisma().getTotal() + "");
		txtCharisma.setTitle(statBlock.getCharisma().getTooltip());
		
		// Item Bonus
		if(statBlock.getStrengthItemBonus() != 0)
			txtStrengthItemBonus.setText(statBlock.getStrengthItemBonus() + "");
		else
			txtStrengthItemBonus.setText("");
		if(statBlock.getDexterityItemBonus() != 0)
			txtDexterityItemBonus.setText(statBlock.getDexterityItemBonus() + "");
		else
			txtDexterityItemBonus.setText("");
		if(statBlock.getConstitutionItemBonus() != 0)
			txtConstitutionItemBonus.setText(statBlock.getConstitutionItemBonus() + "");
		else
			txtConstitutionItemBonus.setText("");
		if(statBlock.getIntelligenceItemBonus() != 0)
			txtIntelligenceItemBonus.setText(statBlock.getIntelligenceItemBonus() + "");
		else
			txtIntelligenceItemBonus.setText("");
		if(statBlock.getWisdomItemBonus() != 0)
			txtWisdomItemBonus.setText(statBlock.getWisdomItemBonus() + "");
		else
			txtWisdomItemBonus.setText("");
		if(statBlock.getCharismaItemBonus() != 0)
			txtCharismaItemBonus.setText(statBlock.getCharismaItemBonus() + "");
		else
			txtCharismaItemBonus.setText("");
		
		// Ability Modifier
		txtSTR.setText(statBlock.getSTR() + "");
		txtSTR.setTitle("(" + statBlock.getStrength().getTotal() + " + " + statBlock.getStrengthItemBonus() + " - 10) / 2 = " + statBlock.getSTR());
		txtDEX.setText(statBlock.getDEX() + "");
		txtDEX.setTitle("(" + statBlock.getDexterity().getTotal() + " + " + statBlock.getDexterityItemBonus() + " - 10) / 2 = " + statBlock.getDEX());
		txtCON.setText(statBlock.getCON() + "");
		txtCON.setTitle("(" + statBlock.getConstitution().getTotal() + " + " + statBlock.getConstitutionItemBonus() + " - 10) / 2 = " + statBlock.getCON());
		txtINT.setText(statBlock.getINT() + "");
		txtINT.setTitle("(" + statBlock.getIntelligence().getTotal() + " + " + statBlock.getIntelligenceItemBonus() + " - 10) / 2 = " + statBlock.getINT());
		txtWIS.setText(statBlock.getWIS() + "");
		txtWIS.setTitle("(" + statBlock.getWisdom().getTotal() + " + " + statBlock.getWisdomItemBonus() + " - 10) / 2 = " + statBlock.getWIS());
		txtCHA.setText(statBlock.getCHA() + "");
		txtCHA.setTitle("(" + statBlock.getCharisma().getTotal() + " + " + statBlock.getCharismaItemBonus() + " - 10) / 2 = " + statBlock.getCHA());
		
		// Feats & Special Abilities
		int i = 0;
		for(Trait trait : character.getRace().getTraits()) {
			lblFeats[i].setText(trait.getName());
			lblFeats[i++].setTitle(trait.getType() + ": " + trait.getDescription());
			
			lblFeats[i].setText("-" + trait.getShortDescription());
			lblFeats[i++].setTitle(trait.getType() + ": " + trait.getDescription());
		}
		
		for(Trait trait : character.getTraits()) {
			lblFeats[i].setText(trait.getName());
			lblFeats[i++].setTitle(trait.getType() + ": " + trait.getDescription());
			
			lblFeats[i].setText("-" + trait.getShortDescription());
			lblFeats[i++].setTitle(trait.getType() + ": " + trait.getDescription());
		}
		
		// Languages
		i = 0;
		for(String language : character.getRace().getLanguages()) {
			lblLanguages[i++].setText(language);
		}
		
		for(String language : character.getLanguages()) {
			lblLanguages[i++].setText(language);
		}
		
		// Classes
		i = 0;
		for(Class c : character.getClasses()) {
			if(c.isFavored()) {
				chkFavoredClasses[i].addStyleName(style.checked());
			}
			lblClassNames[i].setText(c.getName());
			lblClassNames[i].setTitle(c.getDescription());
			lblClassSkillRanks[i].setText(c.getSkillRanks() + "");
			lblClassHitDie[i].setText("d" + c.getHitDie());
			lblClassLevels[i].setText(c.getLevels().size() + "");
		}
		
		// Skills
		i = 0;
		for(StatBlockSkill skill : statBlock.getSkills()) {
			if(i == skillRows.length)
				break;
			
			skillRows[i].setSkill(skill.getSkill(), i == 0 ? null : skillRows[i-1]);
			skillRows[i++].setStats(statBlock.getModifier(skill.getSkill().getModifierName()), skill.getSkill().getModifierName(), skill.isClassSkill(), skill.getClasses(), skill.getFeats(), skill.getPenalty(), skill.getBonus());
		}
		//skillRows[skillRows.length-1].setLast();
	}
	
	private void setAlignment(Alignment alignment) {
		chkLawfulGood.removeStyleName(style.checked());
		chkLawfulNeutral.removeStyleName(style.checked());
		chkLawfulEvil.removeStyleName(style.checked());
		chkNeutralGood.removeStyleName(style.checked());
		chkNeutral.removeStyleName(style.checked());
		chkNeutralEvil.removeStyleName(style.checked());
		chkChaoticGood.removeStyleName(style.checked());
		chkChaoticNeutral.removeStyleName(style.checked());
		chkChaoticEvil.removeStyleName(style.checked());
		
		switch(alignment) {
			case LAWFUL_GOOD: chkLawfulGood.addStyleName(style.checked()); break;
			case LAWFUL_NEUTRAL: chkLawfulNeutral.addStyleName(style.checked()); break;
			case LAWFUL_EVIL: chkLawfulEvil.addStyleName(style.checked()); break;
			case NEUTRAL_GOOD: chkNeutralGood.addStyleName(style.checked()); break;
			case NEUTRAL: chkNeutral.addStyleName(style.checked()); break;
			case NEUTRAL_EVIL: chkNeutralEvil.addStyleName(style.checked()); break;
			case CHAOTIC_GOOD: chkChaoticGood.addStyleName(style.checked()); break;
			case CHAOTIC_NEUTRAL: chkChaoticNeutral.addStyleName(style.checked()); break;
			case CHAOTIC_EVIL: chkChaoticEvil.addStyleName(style.checked()); break;
		}
	}
	
	private void setSex(Sex sex) {
		chkMale.removeStyleName(style.checked());
		chkFemale.removeStyleName(style.checked());
		
		switch(sex) {
			case MALE: chkMale.addStyleName(style.checked()); break;
			case FEMALE: chkFemale.addStyleName(style.checked()); break;
		}
	}
}
